/**
 * TextFormatter
 *
 * @author Chris Pratt
 *
 * 9/25/2009
 */
package com.anodyzed.onyx.text;

import com.anodyzed.onyx.bean.BeanUtils;
import com.anodyzed.onyx.log.Log;
import com.anodyzed.onyx.log.LogBuilder;
import com.anodyzed.onyx.util.Misc;

import java.beans.IntrospectionException;
import java.util.Map;

public abstract class TextFormatter {
  private static final Log log = LogBuilder.getLogger();
  
  protected TextFormat parent;
  private TextFormatter next;
  private String key;
  private String bean;

  /**
   * Constructor
   *  
   * @param parent The Parent TextFormat 
   * @param key The Argument Index or Map Key for this node 
   * @param bean The additional Bean reference string
   */
  public TextFormatter (TextFormat parent,CharSequence key,CharSequence bean) {
    this.parent = parent;
    this.key = (key != null) ? key.toString() : null;
    this.bean = (bean != null) ? bean.toString() : null;
  } //TextFormatter

  /**
   * Convert the Node to a String
   *
   * @param args The Formatting Arguments
   * @return The Formatted String
   */
  public abstract String toString(Object... args);

  /**
   * Get the Value for the Node
   *
   * @param args The Array of Arguments
   * @return The Node Value
   */
  public Object getValue (Object... args) {
    if(Misc.isNumeric(key)) {
      int ndx = Integer.parseInt(key);
      if(args[ndx] != null) {
        if(bean != null) {
          try {
            return BeanUtils.getValue(args[ndx],bean);
          } catch(IntrospectionException x) {
            if(log.isTraceEnabled()) {
              log.trace("Failed Introspecting " + args[ndx] + " for '" + bean + '\'',x);
            }
            return null;
          }
        } else {
          return args[ndx];
        }
      }
    } else if(args[0] instanceof Map<?,?>) {
      if(bean != null) {
        try {
          return BeanUtils.getValue(((Map<?,?>)args[0]).get(key),bean);
        } catch(IntrospectionException x) {
          if(log.isTraceEnabled()) {
            log.trace("Failed Introspecting " + args[0] + " for '" + bean + '\'',x);
          }
        }
      } else {
        return ((Map<?,?>)args[0]).get(key);
      }
    } else {
      if(bean != null) {
        try {
          return BeanUtils.getValue(args[0],key + '.' + bean);
        } catch(IntrospectionException x) {
          if(log.isTraceEnabled()) {
            log.trace("Failed Introspecting " + args[0] + " for '" + key + '.' + bean + '\'',x);
          }
        }
      } else {
        try {
          return BeanUtils.getValue(args[0],key);
        } catch(IntrospectionException x) {
          if(log.isTraceEnabled()) {
            log.trace("Failed Introspecting " + args[0] + " for '" + key + '\'',x);
          }
        }
      }
    }
    return null;
  } //getValue

  /**
   * Get the value of the next attribute. 
   *
   * @return The next value as a TextFormatter
   */
  public TextFormatter getNext () {
    return next;
  } //getNext
  
  /**
   * Set the value of the next attribute.
   *
   * @param next The new next value as a TextFormatter
   */
  public void setNext (TextFormatter next) {
    this.next = next;
  } //setNext

} //*TextFormatter
